#include <iostream>
#include <vector>
#include <queue>
#include "pthread.hpp"
#include <pthread.h>
#include <string>
#include <time.h>
#include "LOG.hpp"
#include "Task copy.hpp"

using namespace std;
using namespace ThreadModule;

template <class T>
class thread_pool
{
private:
    void Lockqueue()
    {
        pthread_mutex_lock(&_mutex);
    }

    void Unlockqueue()
    {
        pthread_mutex_unlock(&_mutex);
    }

    void Sleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }

    void Wakeup()
    {
        pthread_cond_signal(&_cond);
    }

    void WakeAll()
    {
        pthread_cond_broadcast(&_cond);
    }
public:
    thread_pool(int threadnum)
        : _threadnum(threadnum), _waitnum(0), _isrunning(false)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        LOG(1,g_issave,"Thread_pool Construct Success");
    }
    // 处理任务
    void Handler(string name)
    {
        // 上锁保护
        Lockqueue();
        while (1)
        {
            // 队列如果没任务，线程是启动了的,需要等待
            while (_taskqueue.empty() && _isrunning)
            {
                _waitnum++;
                Sleep();
                _waitnum--;
            }
            //1.队列没任务，线程池也结束了
            if (_taskqueue.empty() && !_isrunning)
            {
                Unlockqueue();
                break;
            }
            //2.队列有任务，线程池没结束
            //3.队列有任务，线程池结束了————处理完所有任务再退出
            // 有任务，拿出来
            T t = _taskqueue.front();
            _taskqueue.pop();
            Unlockqueue();
            // 处理任务,这个任务属于这个线程独占的任务，不属于共享资源了。
            LOG(1,g_issave,"%s Handler Task",name.c_str());
            t();
            LOG(1,g_issave,"%s Handler Success ,result is : %s",name.c_str(),t.Result().c_str());
        }
    }

    void Init()
    {
        for (int i = 0; i < _threadnum; i++)
        {
            string name = "thread-" + to_string(i + 1);
            _threads.emplace_back(bind(&thread_pool::Handler, this,placeholders::_1), name);
            LOG(1,g_issave,"%s Init Success",name.c_str());
        }
        _isrunning = true;

    }
    // push任务
    bool Enqueue(const T &in)
    {
        Lockqueue();
        bool ret = false;
        if (_isrunning)
        {
            _taskqueue.push(in);
            // 有任务了，唤醒线程
            if (_waitnum > 0)
            {
                Wakeup();
            }
            ret = true;
        }

        Unlockqueue();

        return ret;
    }

    void Start()
    {
        for (auto &thread : _threads)
        {
            thread.Start();
            LOG(1,g_issave,"%s Start Success",thread.name().c_str());
        }
    }

    void Stop()
    {
        Lockqueue();
        
        _isrunning = false;
        //停止之后，唤醒所有线程，处理任务队列中剩下的任务
        WakeAll();

        Unlockqueue();
    }
    void Wait()
    {
        for (auto &thread : _threads)
        {
            thread.Join();
            LOG(1,g_issave,"%s Wait Success",thread.name().c_str());
        }
    }
    ~thread_pool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        LOG(1,g_issave,"Thread_pool Destory Success");
    }

private:
    vector<Thread> _threads;
    int _threadnum;
    queue<T> _taskqueue;

    // 互斥 + 同步
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    int _waitnum;

    bool _isrunning;
};